"""
:synopsis: Splits ESN FC into Standard ESZ and ESB FCs
:authors: Riley Baird (OK), Emma Baker (OK)
"""
import logging
from itertools import chain

from ...lib.gdbsession import NG911Session, GPMessenger
from ...lib.misc import NGUIDAssignMethod as NAM, unwrap, params_to_dict
from ...lib.eszconst import *

import arcpy

_logger = logging.getLogger(__name__)

def _update_field_filters(parameters: list[arcpy.Parameter]) -> None:
    param_dict = params_to_dict(parameters)
    source_esn_feature_class: str = unwrap(param_dict["source_esn_feature_class"])
    try:
        source_field_names: list[str] = [SET_TO_NULL, *[f.name for f in arcpy.ListFields(source_esn_feature_class)]]
    except:
        source_field_names: list[str] = [SET_TO_NULL]

    for target_parameter_name in ("esz_field_map", "common_field_map", "esb_field_map"):
        target_parameter = param_dict[target_parameter_name]
        try:
            target_parameter.filters[1].list = source_field_names.copy()
            _logger.debug(f"Updated filter for {target_parameter_name} to include: {source_field_names}.")
            _logger.debug(f"Actual filter for {target_parameter_name}: {target_parameter.filters[1].list}.")
            standard_fields: list[str] = [row[0] for row in target_parameter.values]

            # Attempt to match source field names to standard field names
            matched_fields: dict[str, str | None] = {
                matched_standard_field: source_field
                for source_field in source_field_names
                if (matched_standard_field := config.get_closest_field_name(source_field, standard_fields))
            }
            # Autofill the value table with matched source field names; default unmatched fields to "== SET TO NULL =="
            target_parameter.values = [
                [standard_field, matched_fields.get(standard_field, SET_TO_NULL)]
                for standard_field, _
                in target_parameter.values
            ]
        except Exception as exc:
            target_parameter.enabled = False
            _logger.info(f"Failed to update filter for {target_parameter_name}.", exc_info=exc)
        else:
            target_parameter.enabled = True

def _get_parameter_for_field(parameters: list[arcpy.Parameter], standard_field_name: str) -> arcpy.Parameter:
    param_dict = params_to_dict(parameters)
    for target_parameter_name in ("esz_field_map", "common_field_map", "esb_field_map"):
        target_parameter = param_dict[target_parameter_name]
        standard_field_names: list[str] = [row[0] for row in target_parameter.values]
        if standard_field_name in standard_field_names:
            return target_parameter
    raise KeyError(f"None of the field map parameters contain a standard field called '{standard_field_name}'.")


class SplitESN:
    def __init__(self):
        """Define the tool (tool name is the name of the class)."""
        self.label = "4 - Create Standard ESZ & ESB Feature Classes"
        self.description = "Creates Standard ESZ & ESB Feature Classes from user-specified ESN Feature Class."
        self.canRunInBackground = False
        self.category = "1 - Prep"

    def getParameterInfo(self):
        """Define parameter definitions"""
        params = [
            source_esn_feature_class := arcpy.Parameter(
                displayName="Source ESN Feature Class",
                name="source_esn_feature_class",
                datatype="DEFeatureClass",
                parameterType="Required",
                direction="Input"
            ),
            geodatabase := arcpy.Parameter(
                displayName="Destination NG911 Geodatabase",
                name="geodatabase",
                datatype="DEWorkspace",
                parameterType="Required",
                direction="Input"
            ),
            assign_esb_nguids := arcpy.Parameter(
                displayName="Assign Sequential NGUIDs to ESB Feature Classes",
                name="assign_esb_nguids",
                datatype="GPBoolean",
                parameterType="Optional",
                direction="Input"
            ),
            esz_nguid_method := arcpy.Parameter(
                displayName=f"{nguid_esz} Assignment Method",
                name="esz_nguid_method",
                datatype="GPString",
                parameterType="Optional",
                direction="Input"
            ),
            convert_esz_nguids := arcpy.Parameter(
                displayName="Convert ESZ NGUIDs from v2.2 to v3",
                name="convert_esz_nguids",
                datatype="GPBoolean",
                parameterType="Optional",
                direction="Input"
            ),
            esb_to_display_name := arcpy.Parameter(
                displayName=f"Copy ESB Field to {dsplayname}",
                name="esb_to_display_name",
                datatype="GPBoolean",
                parameterType="Optional",
                direction="Input"
            ),
            esz_field_map := arcpy.Parameter(
                displayName="ESZ Field Map",
                name="esz_field_map",
                datatype="GPValueTable",
                parameterType="Optional",
                direction="Input"
            ),
            common_field_map := arcpy.Parameter(
                displayName="ESZ & ESB Field Map",
                name="common_field_map",
                datatype="GPValueTable",
                parameterType="Optional",
                direction="Input"
            ),
            esb_field_map := arcpy.Parameter(
                displayName="ESB Field Map",
                name="esb_field_map",
                datatype="GPValueTable",
                parameterType="Optional",
                direction="Input"
            ),

            # OUTPUT
            # Order as of Standards v3: EMS, FIRE, LAW, ESZ
            output_ems_feature_class := arcpy.Parameter(
                displayName=f"Output {config.feature_classes.esb_ems_boundary.name} Feature Class",
                name="output_ems_feature_class",
                datatype="DEFeatureClass",
                parameterType="Derived",
                direction="Output"
            ),
            output_fire_feature_class := arcpy.Parameter(
                displayName=f"Output {config.feature_classes.esb_fire_boundary.name} Feature Class",
                name="output_fire_feature_class",
                datatype="DEFeatureClass",
                parameterType="Derived",
                direction="Output"
            ),
            output_law_feature_class := arcpy.Parameter(
                displayName=f"Output {config.feature_classes.esb_law_boundary.name} Feature Class",
                name="output_law_feature_class",
                datatype="DEFeatureClass",
                parameterType="Derived",
                direction="Output"
            ),
            output_esz_feature_class := arcpy.Parameter(
                displayName=f"Output {config.feature_classes.esz_boundary.name} Feature Class",
                name="output_esz_feature_class",
                datatype="DEFeatureClass",
                parameterType="Derived",
                direction="Output"
            )
        ]

        esz_nguid_method.filter.list = [*NAM]
        esz_nguid_method.value = "NGUID"

        # Get fields needed for field map
        required_fields = (cf.agency_id, cf.esz, cf.ems, cf.fire, cf.law)
        fields_to_map: set[NG911Field] = {*chain(
            *(fc.fields.values() for fc in (esz, ems, fire, law))
        )}  # All fields in ESB/ESZ feature classes
        fields_to_map: set[NG911Field] = {
            field
            for fc in (esz, ems, fire, law)
            for field in fc.fields.values()
        }  # All fields in ESB/ESZ feature classes
        fields_to_map -= {fc.unique_id for fc in (ems, fire, law)}  # Remove ESB (but not ESZ) NGUID fields
        fields_to_map_ordered: list[str] = [f.name for f in required_fields] + sorted([f.name for f in fields_to_map - set(required_fields)])

        # Set up field map value tableS
        esz_field_map.columns = [['GPString', 'Standard Field', 'ReadOnly'], ['GPString', 'Input Field']]
        esz_field_map.filters[1].type = "ValueList"
        esz_field_map.filters[1].list = [SET_TO_NULL]
        esz_field_map.values = [[f, SET_TO_NULL] for f in esz_field_map_parameter_field_names]
        esz_field_map.enabled = False

        common_field_map.columns = [['GPString', 'Standard Field', 'ReadOnly'], ['GPString', 'Input Field']]
        common_field_map.filters[1].type = "ValueList"
        common_field_map.filters[1].list = [SET_TO_NULL]
        common_field_map.values = [[f, SET_TO_NULL] for f in common_field_map_parameter_field_names]
        common_field_map.enabled = False

        esb_field_map.columns = [['GPString', 'Standard Field', 'ReadOnly'], ['GPString', 'Input Field']]
        esb_field_map.filters[1].type = "ValueList"
        esb_field_map.filters[1].list = [SET_TO_NULL]
        esb_field_map.values = [[f, SET_TO_NULL] for f in esb_field_map_parameter_field_names]
        esb_field_map.enabled = False

        return params

    def isLicensed(self):
        """Set whether tool is licensed to execute."""
        return True

    def updateParameters(self, parameters: list[arcpy.Parameter]):
        """Modify the values and properties of parameters before internal
        validation is performed.  This method is called whenever a parameter
        has been changed."""
        source_esn_feature_class, geodatabase, assign_esb_nguids, esz_nguid_method, convert_esz_nguids, esb_to_display_name, esz_field_map, common_field_map, esb_field_map = parameters[:9]

        if source_esn_feature_class.altered and not source_esn_feature_class.hasBeenValidated:
            # Input feature class just changed; prepare field map table
            try:
                _update_field_filters(parameters)
            except Exception as exc:
                _logger.info("Could not update field map tables:", exc_info=exc)
            else:
                _logger.info("Updated field map tables.")

        if not esz_nguid_method.hasBeenValidated:
            # Only allow convert_esz_nguids if esz_nguid_method is 'NGUID'
            if unwrap(esz_nguid_method) == NAM.NGUID:
                convert_esz_nguids.enabled = True
            else:
                convert_esz_nguids.value = False
                convert_esz_nguids.enabled = False

    def updateMessages(self, parameters: list[arcpy.Parameter]):
        """Modify the messages created by internal validation for each tool
        parameter.  This method is called after internal validation."""
        param_dict = params_to_dict(parameters)
        source_esn_feature_class, geodatabase, assign_esb_nguids, esz_nguid_method, convert_esz_nguids, esb_to_display_name, esz_field_map, common_field_map, esb_field_map = parameters[:9]

        missing_fields_messages: dict[str, list[str]] = {
            "esz_field_map": [],
            "common_field_map": [],
            "esb_field_map": []
        }
        provided_standard_field_names: set[str] = {
            standard
            for field_map in (esz_field_map, common_field_map, esb_field_map)
            for standard, user in unwrap(field_map)
            if user != SET_TO_NULL}

        for field_map in (esz_field_map, common_field_map, esb_field_map):
            parameter_standard_fields = {standard for standard, _ in unwrap(field_map)}
            if missing_fields := (always_required_standard_field_names & parameter_standard_fields) - provided_standard_field_names:
                missing_fields_messages[field_map.name].append(f"Source fields are missing for the following required standard fields: {', '.join(missing_fields)} ")

        # if missing_fields := always_required_standard_field_names - provided_standard_field_names:
        #     missing_fields_messages.append(f"Source fields are missing for the following required standard fields: {', '.join(missing_fields)} ")

        nguid_required: bool = unwrap(esz_nguid_method) in {NAM.NGUID, NAM.COPY}
        agency_id_required: bool = bool(unwrap(assign_esb_nguids)) or unwrap(esz_nguid_method) in {NAM.NGUID, NAM.LOCAL, NAM.SEQUENTIAL}
        localid_required: bool = unwrap(esz_nguid_method) == NAM.LOCAL

        if agency_id_required and agencyid_f.name not in provided_standard_field_names:
            containing_parameter = _get_parameter_for_field(parameters, agencyid_f.name)
            missing_fields_messages[containing_parameter.name].append(f"When '{assign_esb_nguids.displayName}' is selected or a method is selected for'{esz_nguid_method.displayName}', a source field is required for '{agencyid_f.name}'.")

        if nguid_required and nguid_esz not in provided_standard_field_names:
            containing_parameter = _get_parameter_for_field(parameters, nguid_esz)
            missing_fields_messages[containing_parameter.name].append(f"When '{esz_nguid_method.displayName}' is set to 'NGUID' or 'COPY', a source field is required for '{nguid_esz}'.")

        if localid_required and localid_f.name not in provided_standard_field_names:
            containing_parameter = _get_parameter_for_field(parameters, localid_f.name)
            missing_fields_messages[containing_parameter.name].append(f"When '{esz_nguid_method.displayName}' is set to 'LOCAL', a source field is required for '{localid_f.name}'.")

        for parameter_name, messages in missing_fields_messages.items():
            if messages:
                param_dict[parameter_name].setErrorMessage("\n".join(messages))
            else:
                param_dict[parameter_name].clearMessage()


    def execute(self, parameters: list[arcpy.Parameter], messages: GPMessenger):
        """The source code of the tool."""
        ## Process parameters from user-specified values
        esn_fc = unwrap(parameters[0])
        gdb_path = unwrap(parameters[1])
        assign_esb_nguids: bool = unwrap(parameters[2]) or False
        esz_nguid_method: NAM | None = NAM(m) if (m := unwrap(parameters[3])) in set(NAM) else None
        convert_nguids: bool = unwrap(parameters[4]) or False
        esb_to_display_name = unwrap(parameters[5]) or False
        esz_field_table = parameters[6]
        common_field_table = parameters[7]
        esb_field_table = parameters[8]

        with NG911Session(gdb_path, False, False, messages) as session:
            results = session.import_esn_polygons(
                source_fc=esn_fc,
                field_map={
                    standard: user if user != SET_TO_NULL else None
                    for field_table in (esz_field_table, common_field_table, esb_field_table)
                    for standard, user in field_table.values
                },
                esz_nguid_method=esz_nguid_method,
                convert_nguids=convert_nguids,
                assign_sequential_nguids=assign_esb_nguids,
                esb_to_display_name=esb_to_display_name,
                overwrite=True
            )

        parameters[-4].value = str(r) if (r := results[0]) else None
        parameters[-3].value = str(r) if (r := results[1]) else None
        parameters[-2].value = str(r) if (r := results[2]) else None
        parameters[-1].value = str(r) if (r := results[3]) else None
















# random_start_phrase = random.choice(['Make it so!', 'Hello World!', 'As the prophecy foretold...', 'Greetings earthlings.', 'All are bases are belong to us.', 'The Jig is up!'])
#
# required_dataset_name = config.gdb_info.required_dataset_name
# optional_dataset_name = config.gdb_info.optional_dataset_name
# tool_switch: str = "SPLIT_ESN"
#
# gis_urn_default_value = config.gdb_info.nguid_urn_prefix
#
# stat_method = "CONCATENATE"
# sep_string = "||"
#
#
# class ErrorList(StrEnum):
#     select_fc = "PLEASE SELECT A FEATURE CLASS TO MAP"
#     no_fields_found = "NO FIELDS FOUND IN SELECTED FC"
#     select_field = "--PLEASE SELECT FIELD--"
#
#
# # error_list = ["PLEASE SELECT A FEATURE CLASS TO MAP", "NO FIELDS FOUND IN SELECTED FC", "--PLEASE SELECT FIELD--"]
# ## FC STD NAMES
# esz_fc_config_name = config.feature_classes.esz_boundary.name
# ems_fc_config_name = config.feature_classes.esb_ems_boundary.name
# law_fc_config_name = config.feature_classes.esb_law_boundary.name
# fire_fc_config_name = config.feature_classes.esb_fire_boundary.name
# ## ESZ FIELD LIST
# esz_std_field_list = [field.name for field in config.feature_classes.esz_boundary.fields.values()]
# ## FIELDS FOR ANALYSIS
# agency_field = config.fields.agency_id.name
# ems_field = config.fields.ems.name
# law_field = config.fields.law.name
# fire_field = config.fields.fire.name
# esz_field = config.fields.esz.name
# ## REQUIRED FIELD LIST
# dissolve_field_list = [esz_field, ems_field, law_field, fire_field]
#
#
# class _SplitESNTool(object):
#     def __init__(self):
#         """Define the tool (tool name is the name of the class)."""
#         self.label = "4 - Create Standard ESZ & ESB Feature Classes"
#         self.description = "Creates Standard ESZ & ESB Feature Classes from user-specified ESN Feature Class."
#         self.canRunInBackground = False
#         self.category = "1 - Prep"
#
#     def getParameterInfo(self):
#         """Define parameter definitions"""
#
#         params = []
#
#         geodatabase = arcpy.Parameter(
#             displayName="NG911 Standard Geodatabase",
#             name="geodatabase",
#             datatype="DEWorkspace",
#             parameterType="Required",
#             direction="Input"
#         )
#         params += [geodatabase]
#
#         esn_fc = arcpy.Parameter(
#             displayName=f"ESN Feature Class\n  Must contain equivalent field for {agency_field}, {esz_field}, {ems_field}, {law_field}, & {fire_field}.",
#             name="esn_fc",
#             datatype="DEFeatureClass",
#             parameterType="Required",
#             direction="Input"
#         )
#         params += [esn_fc]
#
#         assign_nguid = arcpy.Parameter(
#             displayName=f"Automatically assign NGUIDs to Standard FCs?\n  `NGUID`: Existing Standard-formatted?\n  `LOCAL`: Alphanumeric (requires field)?\n  `SEQUENTIAL`: Sequential number by 1?",
#             name="assign_nguid",
#             datatype="GPString",
#             parameterType="Optional",
#             direction="Input"
#         )
#         assign_nguid.filter.type = "ValueList"
#         assign_nguid.filter.list = [str(x) for x in NAM]
#         assign_nguid.value = "NGUID"
#         params += [assign_nguid]
#
#         field_nguid = arcpy.Parameter(
#             displayName=f"\nField to use for NGUIDs (LOCAL or NGUID)\n  [Note(s):\n    1. If 'SEQUENTIAL' is selected or to evaluate std field as <NULL>, use value: `{ErrorList.select_field}`]",
#             name="field_nguid",
#             datatype="GPString",
#             parameterType="Optional",
#             direction="Input"
#         )
#         field_nguid.parameterDependencies = [esn_fc.name, assign_nguid.name]
#         field_nguid.filter.type = "ValueList"
#         field_nguid.filter.list = [ErrorList.select_fc]
#         field_nguid.value = ErrorList.select_fc
#         params += [field_nguid]
#
#         ems_std_field_list = [field.name for field in config.feature_classes.esb_ems_boundary.fields.values() if 'nguid' not in field.role and field.name != agency_field] # No NGUID and agency fields
#         law_std_field_list = [field.name for field in config.feature_classes.esb_law_boundary.fields.values() if 'nguid' not in field.role and field.name != agency_field] # No NGUID and agency fields
#         fire_std_field_list = [field.name for field in config.feature_classes.esb_fire_boundary.fields.values() if 'nguid' not in field.role and field.name != agency_field] # No NGUID and agency fields
#
#         ## FULL FIELD LIST FOR CREATING ENTIRE ANALYSIS
#         field_to_map_list = set()
#         for field_list in [esz_std_field_list, ems_std_field_list, law_std_field_list, fire_std_field_list]:
#             field_to_map_list.update([field for field in field_list if 'esn' not in field.lower() and 'esz' not in field.lower() and 'ems' not in field.lower() and 'fire' not in field.lower() and 'law' not in field.lower() and 'nguid' not in field.lower() and field != agency_field])
#         std_fc_name_list = [agency_field, esz_field, ems_field, law_field, fire_field] + list(field_to_map_list)
#         std_fc_name_value_list = [[field, ErrorList.select_fc] for field in std_fc_name_list]
#
#         disp_parameter_name = f"\nField Map for Analysis\n  [Note(s):\n    1. `{agency_field}`, `{esz_field}`, `{ems_field}`, `{law_field}`, and `{fire_field}` fields are required to split ESN\n    2. If 'SEQUENTIAL' is selected or to evaluate std field as Null, use value: `{ErrorList.select_field}`]\n"
#         field_table = arcpy.Parameter(
#             displayName=disp_parameter_name,
#             name="field_table",
#             datatype="GPValueTable",
#             parameterType="Optional",
#             direction="Input")
#         field_nguid.parameterDependencies = [esn_fc.name]
#         field_table.columns = [['GPString', 'Schema Field', 'ReadOnly'], ['GPString', 'User-specified Field']]
#         field_table.filters[1].type = "ValueList"
#         field_table.filters[1].list = ["PLEASE SELECT A FEATURE CLASS TO MAP"]
#         field_table.values = std_fc_name_value_list
#         params += [field_table]
#
#         esb_to_display_name = arcpy.Parameter(
#             displayName=f"Copy ESB Field to {config.fields.dsplayname.name}",
#             name="esb_to_display_name",
#             datatype="GPBoolean",
#             parameterType="Optional",
#             direction="Input"
#         )
#         params += [esb_to_display_name]
#
#         # Derived parameters, alphabetical order as of Standards v3
#         out_ems_fc = arcpy.Parameter(
#             displayName=f"Output {config.feature_classes.esb_ems_boundary.name} Feature Class",
#             name="output_ems_feature_class",
#             datatype="DEFeatureClass",
#             parameterType="Derived",
#             direction="Output"
#         )
#         out_fire_fc = arcpy.Parameter(
#             displayName=f"Output {config.feature_classes.esb_fire_boundary.name} Feature Class",
#             name="output_fire_feature_class",
#             datatype="DEFeatureClass",
#             parameterType="Derived",
#             direction="Output"
#         )
#         out_law_fc = arcpy.Parameter(
#             displayName=f"Output {config.feature_classes.esb_law_boundary.name} Feature Class",
#             name="output_law_feature_class",
#             datatype="DEFeatureClass",
#             parameterType="Derived",
#             direction="Output"
#         )
#         out_esz_fc = arcpy.Parameter(
#             displayName=f"Output {config.feature_classes.esz_boundary.name} Feature Class",
#             name="output_esz_feature_class",
#             datatype="DEFeatureClass",
#             parameterType="Derived",
#             direction="Output"
#         )
#         params += [out_ems_fc, out_fire_fc, out_law_fc, out_esz_fc]
#         # index   [    -4          -3           -2          -1    ]
#
#         return params
#
#     def isLicensed(self):
#         """Set whether tool is licensed to execute."""
#         return True
#
#     def updateParameters(self, parameters):
#         """Modify the values and properties of parameters before internal
#         validation is performed.  This method is called whenever a parameter
#         has been changed."""
#         # _logger.debug(f"Parameters altered: {[p.altered for p in parameters]}")
#         esn_fc = parameters[1]
#         assign_nguid_switch = parameters[2]
#         assign_nguid_field = parameters[3]
#         field_table = parameters[4]
#         esb_to_display_name = parameters[5]
#         std_idx = 0
#         user_idx = 1
#         if esn_fc.value and esn_fc.altered and not esn_fc.hasBeenValidated:
#             try:
#                 fc_filter_list = [field.name for field in arcpy.Describe(esn_fc).fields]
#                 possible_nguid = [field for field in fc_filter_list if 'nguid' in field.lower()]
#                 nguid_field = ErrorList.select_field
#                 if len(possible_nguid) == 1 and assign_nguid_switch != "SEQUENTIAL":
#                     nguid_field = possible_nguid[0]
#
#                 nguid_filter_list = [ErrorList.select_field] + fc_filter_list
#             except:
#                 nguid_field = ErrorList.no_fields_found
#                 nguid_filter_list = [ErrorList.no_fields_found]
#             assign_nguid_field.filter.list = nguid_filter_list
#             assign_nguid_field.value = nguid_field
#
#             field_filter_list, new_field_value_list = check_user_fc_for_fields(esn_fc.valueAsText, field_table.values, list(ErrorList), std_idx, user_idx)
#             # field_filter_list.insert(1, USE_ESB_FIELD_KEYWORD)  # Will be replaced with EMS/FIRE/LAW/ESZ, as appropriate, for each output feature class
#             field_table.filters[1].list = field_filter_list
#             if field_table.hasBeenValidated:
#                 # If and only if field_table was *previously* changed (and therefore already validated), overwrite its values
#                 # Without if-block protection, this can overwrite parameters passed in via script call
#                 field_table.values = new_field_value_list
#             field_table.enabled = True
#         elif esn_fc.value and esn_fc.hasBeenValidated and assign_nguid_switch.altered and not assign_nguid_switch.hasBeenValidated:
#             try:
#                 fc_filter_list = [field.name for field in arcpy.Describe(esn_fc).fields]
#                 possible_nguid = [field for field in fc_filter_list if 'nguid' in field.lower()]
#                 nguid_field = ErrorList.select_field
#                 if len(possible_nguid) == 1 and assign_nguid_switch != "SEQUENTIAL":
#                     nguid_field = possible_nguid[0]
#                 nguid_filter_list = [ErrorList.select_field] + fc_filter_list
#             except:
#                 nguid_field = ErrorList.no_fields_found
#                 nguid_filter_list = [ErrorList.no_fields_found]
#             assign_nguid_field.filter.list = nguid_filter_list
#             assign_nguid_field.value = nguid_field
#         elif esn_fc.value and esn_fc.hasBeenValidated and field_table.altered and not field_table.hasBeenValidated:
#             field_table.values = field_table.values
#         elif not esn_fc.value:
#             field_table.enabled = False
#
#         return
#
#     def updateMessages(self, parameters):
#         """Modify the messages created by internal validation for each tool
#         parameter.  This method is called after internal validation."""
#         esn_fc = parameters[1]
#         assign_nguid_switch = parameters[2]
#         assign_nguid_field = parameters[3]
#         field_table = parameters[4]
#         required_fields = {agency_field: True, esz_field: True, ems_field: True, fire_field: True, law_field: True}
#         if esn_fc.value:
#             nguid_field = assign_nguid_field.value
#             if ErrorList.select_fc == nguid_field:
#                 assign_nguid_field.setErrorMessage(f'{ErrorList.select_fc}')
#             elif ErrorList.no_fields_found == nguid_field:
#                 assign_nguid_field.setErrorMessage(f'ISSUES FINDING FIELDS IN FC.')
#             else:
#                 assign_nguid_field.clearMessage()
#             null_field = 0
#             no_fc = False
#             field_issues = False
#             for table_value_list in field_table.values:
#                 schema_field = table_value_list[0]
#                 user_field = table_value_list[1]
#                 if ErrorList.select_fc == user_field:
#                     no_fc = True
#                     break
#                 elif ErrorList.no_fields_found == user_field:
#                     field_issues = True
#                     break
#                 elif (user_field in set(ErrorList) or user_field in ['None','none','False','false',' ','',None]) and (schema_field in list(required_fields.keys())):
#                     required_fields[schema_field] = False
#                 elif ErrorList.select_field == user_field:
#                     null_field += 1
#
#             false_list = [key for key, val in required_fields.items() if not val]
#
#             if no_fc:
#                 field_table.setErrorMessage(f'{ErrorList.select_fc}')
#             elif field_issues:
#                 field_table.setErrorMessage(f'{ErrorList.no_fields_found}')
#             elif false_list:
#                 field_table.setErrorMessage(f'MISSING USER-SPECIFIED FIELD FOR REQUIRED FIELD(S):\n    [{", ".join(false_list)}]')
#             elif null_field > 0:
#                 field_table.setWarningMessage(f'`{null_field}` field(s) will be evaluated as `NULL`.')
#             else:
#                 field_table.clearMessage()
#         else:
#             esn_fc.setErrorMessage(f'{ErrorList.select_fc}')
#
#         return
#
#
#     def execute(self, parameters, messages):
#         """The source code of the tool."""
#         ## Process parameters from user-specified values
#         gdb_path = parameters[0].valueAsText
#         esn_fc = parameters[1].valueAsText
#         assign_nguid_switch: NAM = cast(NAM, NAM[parameters[2].valueAsText])
#         assign_nguid_field = None if parameters[3].valueAsText in set(ErrorList) else parameters[3].valueAsText
#         field_table = parameters[4]
#         esb_to_display_name = parameters[5]
#
#         with NG911Session(gdb_path, False, False, messages) as session:
#             results = session.import_esn_polygons(esn_fc, {
#                 standard:
#                     user if user not in set(ErrorList) else None
#                 for standard, user in field_table.values
#             }, assign_nguid_switch, overwrite=True)
#         parameters[-4].value = results[0]
#         parameters[-3].value = results[1]
#         parameters[-2].value = results[2]
#         parameters[-1].value = results[3]
#
#         return
#
#
#         # fc_dict = {}
#         # for value_list in field_table.values:
#         #     std_field_name = value_list[0]
#         #     dis_field_user_name = value_list[1]
#         #     if dis_field_user_name in set(ErrorList) or 'NGUID' in std_field_name or dis_field_user_name in ['', ' ', 'None', 'Null', None, '#']:
#         #         continue
#         #     fc_dict[std_field_name] = dis_field_user_name
#         #
#         # ## Checking gdb for NG911 dataset
#         # arcpy.AddMessage(f"{random_start_phrase}\n\nCreating Standard ESZ & ESB Feature Classes from user-specified ESN Feature Class `{os.path.basename(esn_fc)}`...")
#         #
#         # esn = ESNtoESZESBFCsImplementer(gdb_path, esn_fc, assign_nguid_switch, assign_nguid_field, fc_dict)
#         # esn.execute_split()
#         #
#         # parameters[-4].value = esn.output_ems_path
#         # parameters[-3].value = esn.output_fire_path
#         # parameters[-2].value = esn.output_law_path
#         # parameters[-1].value = esn.output_esz_path
#         #
#         # return


if __name__ == "__main__":
    raise Exception("This module is a dependency of an ArcGIS Python Toolbox and should not be executed directly.")